#include "relation.h"

#include <QStyleOptionGraphicsItem>
#include <QtMath>
#include <QDebug>
#include <QPen>
#include <QPainter>
#include "port.h"
#include "diagramscene.h"
#include "workflowxml.h"
#include <QtMath>
Relation::Relation(CRelation* _relation,QObject* parent):crelation(_relation),QObject(parent)
{
    setFlag(QGraphicsItem::ItemIsSelectable, true);
    setPen(QPen(myColor, 5, Qt::SolidLine, Qt::RoundCap, Qt::RoundJoin));
    setFlag(QGraphicsItem::ItemIsSelectable, true);
    setAcceptHoverEvents(true);
    if(crelation)
    {
        connect(crelation->srcPort(),&CPort::posChange,this,&Relation::updatePosition);
        connect(crelation->dstPort(),&CPort::posChange,this,&Relation::updatePosition);
        connect(crelation,&CRelation::destroyed,this,[=]()
        {
            scene()->removeItem(this);
            delete this;
        });
    }

}

Relation::~Relation()
{
    qDebug()<<__func__;
}
QRectF Relation::boundingRect() const
{
    qreal extra = (width + 20) / 2.0;

    return QRectF(line().p1(), QSizeF(line().p2().x() - line().p1().x(),
                                      line().p2().y() - line().p1().y()))
        .normalized()
        .adjusted(-extra, -extra, extra, extra);
}



void Relation::updatePosition()
{
    if(crelation!=nullptr)
    {
        qDebug()<<crelation->srcPort()->getPos();
        qDebug()<<crelation->dstPort()->getPos();
        QLineF line(crelation->srcPort()->getPos(),crelation->dstPort()->getPos());
        qDebug()<<"line"<<line;
        setLine(line);
    }
}

void Relation::paint(QPainter *painter, const QStyleOptionGraphicsItem *option,QWidget *widget)
{
    painter->setRenderHint(QPainter::Antialiasing);


    if (option->state & QStyle::State_Selected)
    {
        QPen myPen = pen();
        myPen.setStyle(Qt::DashLine);
        myPen.setColor(Qt::blue);
        myPen.setWidth(width);

        painter->setBrush(myColor);
        painter->setPen(myPen);

    }
    else
    {
        QPen myPen = pen();
        myPen.setStyle(Qt::SolidLine);
        myPen.setColor(myColor);
        myPen.setWidth(width);

        painter->setBrush(myColor);
        painter->setPen(myPen);
    }
    //painter->drawLine(line());
    paintPolygon(painter);

//    int RelationSize = 20;
//    double angle = std::atan2(-line().dy(), line().dx());

//    QPointF RelationP1 = line().p2() - QPointF(sin(angle + M_PI / 3) * RelationSize,
//                                    cos(angle + M_PI / 3) * RelationSize);
//    QPointF RelationP2 = line().p2() - QPointF(sin(angle + M_PI - M_PI / 3) * RelationSize,
//                                    cos(angle + M_PI - M_PI / 3) * RelationSize);
//    QPolygonF polygon;
//    polygon<<line().p2()<<RelationP1<<RelationP2;
//    painter->drawPolygon(polygon);



}

QPainterPath Relation::shape() const
{
    QPainterPath path = QGraphicsLineItem::shape();
    path.addPolygon(myPolygon);
    return path;
}

void Relation::paintPolygon(QPainter *painter)
{
    CPort* srcCport = crelation->srcPort();
    CPort* dstCport = crelation->dstPort();

    auto srcLocation = srcCport->getProperty()->location;
    auto dstLocation = dstCport->getProperty()->location;

    QPointF p1 = line().p1(); //开始位置
    QPointF p2 = line().p2();//结束位置

    QPointF p3 = p1;//开始第一次转折位置
    QPointF p4 = p2;//结束第一次转折位置

    bool startTurn = false; //起点是否转折
    bool endTurn = false; //终点是否转折
    bool srcdirection =false; //false 表示左右 true表示上下
    bool dstdirection =false; //false 表示左右 true表示上下
    if(srcLocation == CPortProperty::TOP)
    {
        if(p1.ry()<p2.ry())
        {
            startTurn = true;
        }
        p3-=QPointF(0,lineLen);
        srcdirection = true;

    }
    else if(srcLocation == CPortProperty::BOTTOM)
    {
        if(p1.ry()>p2.ry())
        {
            startTurn = true;
        }
        p3+=QPointF(0,lineLen);
        srcdirection = true;
    }
    else if(srcLocation == CPortProperty::LEFT)
    {
        if(p1.rx()<p2.rx())
        {
            startTurn = true;
        }
        p3-=QPointF(lineLen,0);
        srcdirection = false;
    }
    else if(srcLocation == CPortProperty::RIGHT)
    {
        if(p1.rx()>p2.rx())
        {
            startTurn = true;
        }
        p3+=QPointF(lineLen,0);
        srcdirection = false;
    }
    if(dstLocation == CPortProperty::TOP)
    {
        if(p1.ry()>p2.ry())
        {
            endTurn = true;
        }
        p4-=QPointF(0,lineLen);
        dstdirection = true;
    }
    else if(dstLocation == CPortProperty::BOTTOM)
    {
        if(p1.ry()<p2.ry())
        {
            endTurn = true;
        }
        p4+=QPointF(0,lineLen);
        dstdirection = true;
    }
    else if(dstLocation == CPortProperty::LEFT)
    {
        if(p1.rx()>p2.rx())
        {
            endTurn = true;
        }
        p4-=QPointF(lineLen,0);
        dstdirection = false;
    }
    else if(dstLocation == CPortProperty::RIGHT)
    {
        if(p1.rx()<p2.rx())
        {
            endTurn = true;
        }
        p4+=QPointF(lineLen,0);
        dstdirection = false;
    }

    myPolygon.clear();
    if(!startTurn && !endTurn)
    {

        int middelX = (p3.rx()+p4.rx())/2;
        int middelY = (p3.ry()+p4.ry())/2;

        myPolygon.append(p1);
        if(srcdirection)
        {
            myPolygon.append(QPointF(p1.rx(),middelY));
            myPolygon.append(QPointF(p1.rx(),middelY));

            myPolygon.append(QPointF(p2.rx(),middelY));
            myPolygon.append(QPointF(p2.rx(),middelY));
        }
        else
        {
            myPolygon.append(QPointF(middelX,p1.ry()));
            myPolygon.append(QPointF(middelX,p1.ry()));

            myPolygon.append(QPointF(middelX,p2.ry()));
            myPolygon.append(QPointF(middelX,p2.ry()));
        }
        myPolygon.append(p2);
        //painter->drawLines(myPolygon);
    }
    else
    {

        myPolygon.append(p1);
        myPolygon.append(p3);

        myPolygon.append(p3);
        if(srcdirection )
        {
            myPolygon.append(QPointF(p4.rx(),p3.ry()));
            myPolygon.append(QPointF(p4.rx(),p3.ry()));
        }
        else
        {
            myPolygon.append(QPointF(p3.rx(),p4.ry()));
            myPolygon.append(QPointF(p3.rx(),p4.ry()));
        }
        myPolygon.append(p4);

        myPolygon.append(p4);
        myPolygon.append(p2);
        //painter->drawLines(myPolygon);

    }
    painter->drawLines(myPolygon);
    int arrowSize = 10;
    QPolygonF arrowPolygon;
    if(dstLocation == CPortProperty::TOP)
    {
        arrowPolygon.append(p2);
        arrowPolygon.append(QPointF(p2.rx()-arrowSize,p2.ry()-arrowSize));
        arrowPolygon.append(QPointF(p2.rx()+arrowSize,p2.ry()-arrowSize));
    }
    else if(dstLocation == CPortProperty::BOTTOM)
    {
        arrowPolygon.append(p2);
        arrowPolygon.append(QPointF(p2.rx()-arrowSize,p2.ry()+arrowSize));
        arrowPolygon.append(QPointF(p2.rx()+arrowSize,p2.ry()+arrowSize));
    }
    else if(dstLocation == CPortProperty::LEFT)
    {
        arrowPolygon.append(p2);
        arrowPolygon.append(QPointF(p2.rx()-arrowSize,p2.ry()-arrowSize));
        arrowPolygon.append(QPointF(p2.rx()-arrowSize,p2.ry()+arrowSize));
    }
    else if(dstLocation == CPortProperty::RIGHT)
    {
        arrowPolygon.append(p2);
        arrowPolygon.append(QPointF(p2.rx()+arrowSize,p2.ry()-arrowSize));
        arrowPolygon.append(QPointF(p2.rx()+arrowSize,p2.ry()+arrowSize));
    }


    painter->drawPolygon(arrowPolygon);


}

CRelation *Relation::getCrelation() const
{
    return crelation;
}

void Relation::setCrelation(CRelation *value)
{
    if(crelation)
    {
        disconnect(crelation);
    }
    crelation = value;
    connect(crelation,&CRelation::destroyed,this,[=]()
    {
        scene()->removeItem(this);
        delete this;
    });
}


